//
// (C) Copyright 2009 Irantha Suwandarathna (irantha@gmail.com)
// All rights reserved.
//

/* Copyright (c) 2001-2008, The HSQL Development Group
 * All rights reserved.
 *
 * Redistribution and use _in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions _in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer _in the documentation
 * and/or other materials provided with the distribution.
 *
 * Neither the name of the HSQL Development Group nor the names of its
 * contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */


using System;
using System.IO;
using System.Text;
using EffiProz.Core.Lib;
using EffiProz.Core.DataTypes;

namespace EffiProz.Core.RowIO
{

    /**
     *  Provides methods for reading the data for a row from a
     *  byte array. The format of data is that used for storage of cached
     *  tables by v.1.6.x databases, apart from strings.
     *
     * @author sqlbob@users (RMP)
     * @author fredt@users
     * @version 1.7.2
     * @since 1.7.0
     */
    public class RowInputBinary : RowInputBase, RowInputInterface
    {

        private RowOutputBinary _out;

        public RowInputBinary(byte[] buf)
            : base(buf)
        {

        }

        /**
         * uses the byte[] buffer from out. At each reset, the buffer is set
         * to the current one for out.
         */
        public RowInputBinary(RowOutputBinary _out)
            : base(_out.getBuffer())
        {

            this._out = _out;
        }

        public override int readType()
        {
            return readShort();
        }

        public override String readString()
        {

            int length = readInt();
            String s = StringConverter.readUTF(buf, pos, length);
            pos += length;

            return s;
        }

        protected override bool checkNull()
        {

            int b = readByte();

            return b == 0 ? true : false;
        }

        protected override String readChar(SqlType type)
        {
            return readString();
        }

        protected override int? readSmallint()
        {
            return readShort();
        }

        protected override int? readInteger()
        {
            return readInt();
        }

        protected override long? readBigint()
        {
            return readLong();
        }

        protected override double? readReal()
        {
            return readDouble();
        }

        protected override decimal? readDecimal(SqlType type)
        {

            return readDecimal();
        }

        protected override bool? readBoolean()
        {
            return readBool();
        }

        protected override TimeData readTime(SqlType type)
        {

            if (type.typeCode == Types.SQL_TIME)
            {
                return new TimeData(readInt(), readInt(), 0);
            }
            else
            {
                return new TimeData(readInt(), readInt(), readInt());
            }
        }

        protected override TimestampData readDate(SqlType type)
        {

            long date = readLong();

            return new TimestampData(date);
        }

        protected override TimestampData readTimestamp(SqlType type)
        {

            if (type.typeCode == Types.SQL_TIMESTAMP)
            {
                return new TimestampData(readLong(), readInt());
            }
            else
            {
                return new TimestampData(readLong(), readInt(), readInt());
            }
        }

        protected override IntervalMonthData readYearMonthInterval(SqlType type)
        {

            long months = readLong();

            return new IntervalMonthData(months, (IntervalType)type);
        }

        protected override IntervalSecondData readDaySecondInterval(SqlType type)
        {

            long seconds = readLong();
            int nanos = readInt();

            return new IntervalSecondData(seconds, nanos, (IntervalType)type);
        }

        protected override Object readOther()
        {
            return new OtherData(readByteArray());
        }

        protected override BinaryData readBit()
        {

            int length = readInt();
            byte[] b = new byte[(length + 7) / 8];

            readFully(b);

            return BinaryData.getBitData(b, length);
        }

        protected override BinaryData readBinary()
        {
            return new BinaryData(readByteArray(), false);
        }

        protected override ClobData readClob()
        {

            long id = base.readLong();

            return new ClobDataID(id);
        }

        protected override BlobData readBlob()
        {

            long id = base.readLong();

            return new BlobDataID(id);
        }

        public override Object[] readData(SqlType[] colTypes)
        {
            return base.readData(colTypes);
        }

        // helper methods
        public byte[] readByteArray()
        {

            byte[] b = new byte[readInt()];

            readFully(b);

            return b;
        }

        public char[] readCharArray()
        {

            char[] c = new char[readInt()];

            if (count - pos < c.Length)
            {
                pos = count;

                throw new EndOfStreamException();
            }

            for (int i = 0; i < c.Length; i++)
            {
                int ch1 = buf[pos++] & 0xff;
                int ch2 = buf[pos++] & 0xff;

                c[i] = (char)((ch1 << 8) + (ch2));
            }

            return c;
        }

        /**
         *  Used to reset the row, ready for Result data to be written into the
         *  byte[] buffer by an external routine.
         *
         */
        public void resetRow(int rowsize)
        {

            if (_out != null)
            {
                _out.reset(rowsize);

                buf = _out.getBuffer();
            }

            base.reset();
        }

        /**
         *  Used to reset the row, ready for a new db row to be written into the
         *  byte[] buffer by an external routine.
         *
         */
        public override void resetRow(int filepos, int rowsize)
        {

            if (_out != null)
            {
                _out.reset(rowsize);

                buf = _out.getBuffer();
            }

            base.resetRow(filepos, rowsize);
        }
    }
}